package com.glw.sso.platform.common.util;

import com.glw.sso.platform.common.exception.BusinessException;
import com.glw.sso.platform.common.exception.SystemException;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 断言
 */
public class Assert {

    /**
     * 判断state
     * @param expression
     * @param message
     */
    public static void state(boolean expression, int code, Object... args) {
        if (!expression) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断表达式为真
     * @param expression
     * @param codeSupplier
     */
    public static void state(boolean expression, Supplier<Integer> codeSupplier, Object... args) {
        if (!expression) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断表达式为真
     * @param expression
     * @param message
     */
    public static void isTrue(boolean expression, int code, Object... args) {
        if (!expression) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断表达式为真
     * @param expression
     * @param codeSupplier
     */
    public static void isTrue(boolean expression, Supplier<Integer> codeSupplier, Object... args) {
        if (!expression) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断对象是否null
     * @param object
     * @param message
     */
    public static void isNull(@Nullable Object object, int code, Object... args) {
        if (object != null) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断对象是否为null
     * @param object
     * @param codeSupplier
     */
    public static void isNull(@Nullable Object object, Supplier<Integer> codeSupplier, Object... args) {
        if (object != null) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }
    /**
     * 判断对象是否为null
     * @param object
     * @param message
     */
    public static void notNull(@Nullable Object object, int code, Object... args) {
        if (object == null) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断对象是否为null
     * @param object
     * @param codeSupplier
     */
    public static void notNull(@Nullable Object object, Supplier<Integer> codeSupplier, Object... args) {
        if (object == null) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断字符串是否为null
     * @param text
     * @param message
     */
    public static void notNull(@Nullable String text, int code, Object... args) {
        if (!StringUtils.hasLength(text)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断字符串是否为空
     * @param text
     * @param codeSupplier
     */
    public static void notNull(@Nullable String text, Supplier<Integer> codeSupplier, Object... args) {
        if (!StringUtils.hasLength(text)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断字符串中字符是否为null
     * @param text
     * @param message
     */
    public static void hasText(@Nullable String text, int code, Object... args) {
        if (!StringUtils.hasText(text)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断字符串中字符是否为null
     * @param text
     * @param codeSupplier
     */
    public static void hasText(@Nullable String text, Supplier<Integer> codeSupplier, Object... args) {
        if (!StringUtils.hasText(text)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }


    /**
     * 判断字符串中是否包含
     * @param textToSearch
     * @param substring
     * @param message
     */
    public static void doesNotContain(@Nullable String textToSearch, String substring, int code, Object... args) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断字符串中是否包含
     * @param textToSearch
     * @param substring
     * @param codeSupplier
     */
    public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<Integer> codeSupplier, Object... args) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断数组是否为null
     * @param array
     * @param message
     */
    public static void notEmpty(@Nullable Object[] array, int code, Object... args) {
        if (ObjectUtils.isEmpty(array)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断数组是否为null
     * @param array
     * @param codeSupplier
     */
    public static void notEmpty(@Nullable Object[] array, Supplier<Integer> codeSupplier, Object... args) {
        if (ObjectUtils.isEmpty(array)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断数组中元素是否为null
     * @param array
     * @param message
     */
    public static void noNullElements(@Nullable Object[] array, int code, Object... args) {
        if (array != null) {
            for (Object element : array) {
                if (element == null) {
                    throw BusinessException.create(code, args);
                }
            }
        }

    }

    /**
     * 判断数组中元素是否为null
     * @param array
     * @param codeSupplier
     */
    public static void noNullElements(@Nullable Object[] array, Supplier<Integer> codeSupplier, Object... args) {
        if (array != null) {
            for (Object element : array) {
                if (element == null) {
                    throw new BusinessException(nullSafeGet(codeSupplier), args);
                }
            }
        }

    }

    /**
     * 判断集合是否为空
     * @param collection
     * @param message
     */
    public static void notEmpty(@Nullable Collection<?> collection, int code, Object... args) {
        if (CollectionUtils.isEmpty(collection)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断集合是否为空
     * @param collection
     * @param codeSupplier
     */
    public static void notEmpty(@Nullable Collection<?> collection, Supplier<Integer> codeSupplier, Object... args) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断map 是否为null
     * @param map
     * @param message
     */
    public static void notEmpty(@Nullable Map<?, ?> map, int code, Object... args) {
        if (CollectionUtils.isEmpty(map)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断map 是否为null
     * @param map
     * @param codeSupplier
     */
    public static void notEmpty(@Nullable Map<?, ?> map, Supplier<Integer> codeSupplier, Object... args) {
        if (CollectionUtils.isEmpty(map)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }
    }

    /**
     * 判断是否输入某个实例
     * @param type
     * @param obj
     * @param message
     */
    public static void isInstanceOf(Class<?> type, @Nullable Object obj, int code, Object... args) {
        notNull(type, code, args);
        if (!type.isInstance(obj)) {
            throw BusinessException.create(code, args);
        }
    }

    /**
     * 判断是否输入某个实例
     * @param type
     * @param obj
     * @param codeSupplier
     */
    public static void isInstanceOf(Class<?> type, @Nullable Object obj, Supplier<Integer> codeSupplier, Object... args) {
        notNull(type, nullSafeGet(codeSupplier), args);
        if (!type.isInstance(obj)) {
            throw new BusinessException(nullSafeGet(codeSupplier), args);
        }

    }

    /**
     * 获取异常信息
     * @param codeSupplier codeSupplier
     * @return code
     */
    @Nullable
    private static int nullSafeGet(@Nullable Supplier<Integer> codeSupplier) {
        return codeSupplier != null ? codeSupplier.get() : SystemException.Code.SYSTEM_ERROR;
    }
}